package com.phospherus.flow.service

import com.phospherus.common.service.impl.BaseServiceImpl
import com.phospherus.flow.entity.FormInst
import com.phospherus.flow.entity.FormItemPermission
import com.phospherus.flow.repository.FormInstRepository
import com.phospherus.user.entity.User
import com.phospherus.user.service.UserService
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import java.util.*

/**
 * @author songjinlong
 * @version 1.0
 * @since 2017/12/21
 */
@Service
@Transactional
class FormInstService : BaseServiceImpl<FormInst, Long, FormInstRepository>() {
    @Autowired
    lateinit var workFlowInstService: WorkFlowInstService
    @Autowired
    lateinit var flowNodeService: FlowNodeService
    @Autowired
    lateinit var userService: UserService
    @Autowired
    lateinit var approvalService: ApprovalService
    @Autowired
    lateinit var formItemPermissionService: FormItemPermissionService
    @Autowired
    lateinit var flowService: FlowService
    @Autowired
    lateinit var hiveToDoService: HiveToDoService
    /**
     * 获取表单数据
     */
    fun getFormInstData(formInstId: Long, formServiceName: String, isHive: String?): MutableMap<String, Any?> {
        var map: MutableMap<String, Any?> = mutableMapOf()
        var fbs: FormInstBaseService? = FormInstBaseService.SERVICE_MAP[formServiceName] ?: throw RuntimeException("$formServiceName is null")
        if (formInstId > 0) {
            var formInst = findOne(formInstId)
            map = fbs!!.query(formInstId)
            var approvals = approvalService.getApprovalsByFormInstId(formInstId)
            map["formInstId"] = formInst.id
            map["flowId"] = formInst.flowId
            map["formId"] = formInst.formId
            map["formServiceName"] = formInst.formServiceName
            map["bindingFormInstId"] = formInst.bindingFormInstId
            map["orderCode"] = formInst.orderCode
            map["approvals"] = approvals
            if (formInst.relationFormInstId != null) {
                map["relationFormInst"] = findOne(formInst.relationFormInstId)
            }
        }
        var currWorkFlowInst = workFlowInstService.getCurrWorkFlowInstByFromInstId(formInstId)
        map["role"] = if (isHive != null && isHive == "1") {
            mapOf(Pair("DEFAULT", "R"))
        } else if (currWorkFlowInst == null) {
            ""
        } else {
            getPermissionByNodeId(currWorkFlowInst?.currNodeId!!)
        }
        return map
    }

    fun getPermissionByNodeId(currNodeId: Long) = formItemPermissionService.getPermissionByNodeId(currNodeId)

    fun getPermission(flowId: Long, currNodeId: Long?): List<FormItemPermission> {
        var cId = currNodeId ?: flowNodeService.getStartNode(flowId).id!!
        return getPermissionByNodeId(cId)
    }

    /**
     * 暂存
     */
    fun temporary(map: MutableMap<String, Any>): Boolean {
        saveForm(map)
        var formInstId = map["formInstId"] as Long
        var currWorkFlowInst = workFlowInstService.getCurrWorkFlowInstByFromInstId(formInstId)
        if (currWorkFlowInst == null) {
            var user = map["USER"] as User?
            var flowId = (map["flowId"] as String).toLong()
            var firstNode = flowNodeService.getStartNode(flowId)
            map["currNodeId"] = firstNode.id!!
            map["workFlowType"] = 1
            if (user != null) {
                map["currUserName"] = user!!.userName!!
                map["currUserId"] = user!!.id!!
            }
            map["finishTime"] = Date()
            workFlowInstService.createWorkFlowInst(map)
        }
        return true
    }
    /**
     * 保存表单数据
     */
    fun saveForm(map: MutableMap<String, Any>): Boolean {
        var flowId = (map["flowId"] as String?)?.toLong() ?: return false
        var formId = (map["formId"] as String?)?.toLong() ?: return false
        var formServiceName = map["formServiceName"] as String? ?: return false
        //绑定订单ID
        var bindingFormInstId = try {
            (map["bindingFormInstId"] as String?)?.toLong()
        } catch (e: NumberFormatException) {
            null
        }
        var orderCode: String = map["orderCode"] as String? ?: "" //订单号
        var ftcCode: String = map["ftcCode"] as String? ?: ""     //外贸合同号
        var buyerName: String = map["buyerName"] as String? ?: "" //买家名称
        var dtcCode: String = map["dtcCode"] as String? ?: ""     //内贸合同号
        var relationFormInstId = try {
            (map["relationFormInstId"] as String?)?.toLong()
        } catch (e: NumberFormatException) {
            null
        }
        var formInstId = (map["formInstId"] as String?)?.toLong()
        var user = map["USER"] as User?
        //处理表单实例对象
        var formInst = if (formInstId != null) {
            findOne(formInstId)
        } else {
            FormInst(formInstStatus = 0, createUserName = user?.userName, createUserId = user?.id) //待发
        }
        var flow = flowService.findOne(flowId)
        save(with(formInst) {
            this.flowId = flowId
            this.formId = formId
            this.flowName = flow.flowName
            this.bindingFormInstId = bindingFormInstId
            this.orderCode = orderCode
            this.ftcCode = ftcCode
            this.buyerName = buyerName
            this.dtcCode = dtcCode
            this.formServiceName = formServiceName
            this.relationFormInstId = relationFormInstId
            this.flowPath = flow.flowPath
            this
        })
        //处理表单填报去数据
        map["formInst"] = formInst
        map["formInstId"] = formInst.id!!
        var fbs: FormInstBaseService? = FormInstBaseService.SERVICE_MAP[formServiceName] ?: return false
        fbs!!.save(map)
        //处理审批意见
        approvalService.saveApproval(map)
        return true
    }
    /**
     * 发送表单
     */
    fun send(map: MutableMap<String, Any>): Boolean {
        var nextNodeId = (map["nextNodeId"] as String?)?.toLong() ?: return false
        var user = map["USER"] as User?
        if (saveForm(map)) {
            var formInstId = map["formInstId"] as Long
            var currWorkFlowInst = workFlowInstService.getCurrWorkFlowInstByFromInstId(formInstId)
            if (currWorkFlowInst == null) {
                var flowId = (map["flowId"] as String).toLong()
                var firstNode = flowNodeService.getStartNode(flowId)
                map["currNodeId"] = firstNode.id!!
                map["workFlowType"] = 2
                if (user != null) {
                    map["currUserName"] = user!!.userName!!
                    map["currUserId"] = user!!.id!!
                }
                map["finishTime"] = Date()
                currWorkFlowInst = workFlowInstService.createWorkFlowInst(map)
            } else {
                currWorkFlowInst.workFlowType = 2
                currWorkFlowInst.finishTime = Date()
                currWorkFlowInst = workFlowInstService.save(currWorkFlowInst)
            }
            var formInst = map["formInst"] as FormInst
            var nextNode = flowNodeService.findOne(nextNodeId)

            if (nextNode != null && nextNode.nodeType == 2) {
                null
            } else {
                var nextUser = userService.getNextUserByRoleIdAndCurrUser(nextNode.roleId!!, formInst.createUserId, user!!)
                map["currUserName"] = nextUser!!.userName!!
                map["currUserId"] = nextUser!!.id!!
            }
            map["currNodeId"] = nextNodeId
            map["workFlowType"] = if (nextNode.nodeType == 0) {
                1
            } else {
                nextNode.nodeType
            }
            map["beforeWorkFlowInstId"] = currWorkFlowInst!!.id!!
            var nextWorkFlowInst = workFlowInstService.createWorkFlowInst(map)
            modifyFormInstStatus(formInstId, nextNode.nodeType)
            hiveToDoService.addHiveToDo(currWorkFlowInst, nextWorkFlowInst, map)
        }
        return true
    }
    fun modifyFormInstStatus(formInstId: Long, status: Int) = repository.modifyFormInstStatus(formInstId, status)
}